package start;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
*
* @author  Tom Lutze
*/
public class PanSharpening {

	private static final int IMG_WIDTH = 400;
	private static final int IMG_HEIGHT = 400;

	public int width_pan;
	public int height_pan;

	public int width_col;
	public int height_col;

	private String colPath;
	private String panPath;
	
	private Boolean isCustomePath;

	private String colCopyPath;

	public BufferedImage colImage;
	public BufferedImage colResizedImage;
	public BufferedImage panImage;
	public BufferedImage panSharpenedImage;
	
	public BufferedImage previewColImage;
	public BufferedImage previewColSmallImage;
	public BufferedImage previewPanImage;
	public BufferedImage previewPanSharpenedImage;
	public BufferedImage previewPanSharpenedBigImage;

	public PanSharpening(String colPath, String panPath, Boolean isCustomePath) {
		this.colPath = colPath;
		this.panPath = panPath;
		this.isCustomePath = isCustomePath;
		this.colCopyPath = "src/tmpres/color_copy.png";
		
		startPanSharpening();
		buildPreviewImages();
	}

	private void startPanSharpening() {

		try {
			if(isCustomePath){
				colImage =  ImageIO.read(new File(colPath));
				panImage =  ImageIO.read(new File(panPath));
			}else {
				colImage =  ImageIO.read(getClass().getResourceAsStream(colPath));
				panImage =  ImageIO.read(getClass().getResourceAsStream(panPath));
			}
			
			width_pan = panImage.getWidth();
			height_pan = panImage.getHeight();

			width_col = colImage.getWidth();
			height_col = colImage.getHeight();
			
			colResizedImage = resizeImage(colImage, width_pan, height_pan, colImage.getType());

			buildPanSharpenedImage(colResizedImage, panImage);

		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	private void copyImage(String sourcepath) {
		try {
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sourcepath)), 4096);
			File targetFile = new File(colCopyPath);
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile), 4096);
			int theChar;

			while ((theChar = bis.read()) != -1) {
				bos.write(theChar);
			}

			bos.close();
			bis.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private static BufferedImage resizeImage(BufferedImage originalImage, int type) {
		BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
		Graphics2D g = resizedImage.createGraphics();
		g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
		g.dispose();

		return resizedImage;
	}

	@SuppressWarnings("unused")
	private static BufferedImage resizeImage(BufferedImage originalImage, int width, int height, int type) {
		BufferedImage resizedImage = new BufferedImage(width, height, type);
		Graphics2D g = resizedImage.createGraphics();
		g.drawImage(originalImage, 0, 0, width, height, null);
		g.dispose();

		return resizedImage;
	}
	
	public void storePanSharpenedImage(String customePath){
		try {
			ImageIO.write(panSharpenedImage, "png", new File(customePath+".png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void buildPanSharpenedImage(BufferedImage bufferedImage, BufferedImage bufferedImagePan) {
		int width = bufferedImage.getWidth(null);
		int height = bufferedImage.getHeight(null);
		int[] pixels = new int[width * height];
		int[] pixelsPan = new int[width * height];
		bufferedImage.getRGB(0, 0, width, height, pixels, 0, width);
		bufferedImagePan.getRGB(0, 0, width, height, pixelsPan, 0, width);

		BufferedImage bufImgColor = new BufferedImage(width_pan, height_pan, BufferedImage.TYPE_INT_RGB);

		bufImgColor.setRGB(0, 0, width, height, rgbToHSB(pixels, pixelsPan), 0, width);

		panSharpenedImage = bufImgColor;
	}

	private int[] rgbToHSB(int[] pixelsColor, int[] pixelsPan) {

		int[] panSharpenedPixels = new int[pixelsColor.length];

		for (int i = 0; i < pixelsColor.length; i++) {
			int rgbColor = pixelsColor[i];
			int rgbPan = pixelsPan[i];

			float[] hsbvalsPan = new float[3];
			float[] hsbvalsColor = new float[3];

			Color.RGBtoHSB(new Color(rgbColor).getRed(), new Color(rgbColor).getGreen(), new Color(rgbColor).getBlue(), hsbvalsColor);
			Color.RGBtoHSB(new Color(rgbPan).getRed(), new Color(rgbPan).getGreen(), new Color(rgbPan).getBlue(), hsbvalsPan);

			int panSharpenedColor = Color.HSBtoRGB(hsbvalsColor[0], hsbvalsColor[1], hsbvalsPan[2]);

			panSharpenedPixels[i] = panSharpenedColor;
		}

		return panSharpenedPixels;
	}

	private void buildPreviewImages() {
		BufferedImage bufColImg = colResizedImage;
		BufferedImage bufColSmallImg = colImage;
		BufferedImage bufPanImg = panImage;
		BufferedImage bufPanSharpenedImg = panSharpenedImage;

		BufferedImage previewPan;
		BufferedImage previewCol;
		BufferedImage previewColSmall;
		BufferedImage previewPanSharpened;
		BufferedImage previewPanSharpenedBig;

		if (width_pan > height_pan) {
			float ratio = (float)200 / width_pan;
			previewPan = resizeImage(bufPanImg, Math.round(width_pan * ratio), Math.round(height_pan * ratio), bufPanImg.getType());
			previewPanSharpened = resizeImage(bufPanSharpenedImg, Math.round(width_pan * ratio), Math.round(height_pan * ratio), bufPanSharpenedImg.getType());
			previewPanSharpenedBig = resizeImage(bufPanSharpenedImg, (int) Math.round(width_pan * ratio * 1.75), (int) Math.round(height_pan * ratio * 1.75), bufPanSharpenedImg.getType());
			previewCol = resizeImage(bufColImg, Math.round(width_pan * ratio), Math.round(height_pan * ratio), bufColImg.getType());
			previewColSmall = resizeImage(bufColSmallImg, Math.round(width_col * ratio), Math.round(height_col * ratio), bufColSmallImg.getType());
		} else {
			float ratio = (float)200 / height_pan;
			previewPan = resizeImage(bufPanImg, Math.round(width_pan * ratio), Math.round(height_pan * ratio), bufPanImg.getType());
			previewPanSharpened = resizeImage(bufPanSharpenedImg, Math.round(width_pan * ratio), Math.round(height_pan * ratio), bufPanSharpenedImg.getType());
			previewPanSharpenedBig = resizeImage(bufPanSharpenedImg, (int) Math.round(width_pan * ratio * 1.75), (int) Math.round(height_pan * ratio * 1.75), bufPanSharpenedImg.getType());
			previewCol = resizeImage(bufColImg, Math.round(width_pan * ratio), Math.round(height_pan * ratio), bufColImg.getType());
			previewColSmall = resizeImage(bufColSmallImg, Math.round(width_col * ratio), Math.round(height_col * ratio), bufColSmallImg.getType());
		}
		
		previewColImage = previewCol;
		previewColSmallImage = previewColSmall;
		previewPanImage = previewPan;
		previewPanSharpenedImage = previewPanSharpened;
		previewPanSharpenedBigImage = previewPanSharpenedBig;
	}
}
